﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using ExtendedMvc.Html;

namespace ExtendedMvc.Elements {
	public class GridCommandColumn<TModel> : GridColumnBase<GridCommandColumn<TModel>, TModel>, IGridCommandColumn<TModel> where TModel : class {
		//private string _keyMemberName;
		private Func<TModel, object> _value;
		private IModelViewHelper<IEnumerable<TModel>> _helper;
		private Expression<Func<TModel, object>> _keyExpression;
		private GridCommandBuilder<TModel> _commands;
		private System.Action<GridCommandBuilder<TModel>> _builder;

		private string _commandsSeparator = "&nbsp;|&nbsp;";

		public GridCommandColumn(System.Action<GridCommandBuilder<TModel>> Builder, Expression<Func<TModel, object>> keyExpression, IModelViewHelper<IEnumerable<TModel>> helper)
			: base(keyExpression.GetMemberExpression() == null ? null : keyExpression.GetMemberExpression().Member.Name) {
			_keyExpression = keyExpression;
			_value = keyExpression.Compile();
			_helper = helper;
			_builder = Builder;
			if (Builder != null) {
				_commands = new GridCommandBuilder<TModel>(helper, keyExpression);
				Builder(_commands);
			}
		}

		public virtual GridCommandColumn<TModel> Separator(string value) {
			_commandsSeparator = value;
			return this;
		}

		public override object GetHeader() {
			var headerCommands = _commands == null ? null : _commands.Where(c => c.Position.HasFlag(GridCommandPosition.Header));
			if (headerCommands == null) {
				var newCommands = new GridCommandBuilder<TModel>(_helper, _keyExpression);
				newCommands.ForHeaderAsAction("New", "New");
				headerCommands = newCommands.Where(c => c.Position.HasFlag(GridCommandPosition.Header));
			}
			var result = string.Empty;
			foreach (IGridCommandBase<TModel> command in headerCommands) {
				var link = string.Empty;
				if (command is GridCommand<TModel>)
					link = (command as GridCommand<TModel>).GetLink();
				else if (command is GridActionCommand<TModel>)
					link = (command as GridActionCommand<TModel>).GetLink();
				else if (command is GridRouteCommand<TModel>)
					link = (command as GridRouteCommand<TModel>).GetLink();
				else
					throw new Exception("Invalid command type");
				result += (result == string.Empty ? string.Empty : _commandsSeparator) + (_helper is ModelViewAjaxHelper<IEnumerable<TModel>> ? (_helper as ModelViewAjaxHelper<IEnumerable<TModel>>).Link(command.Text, link).Render() : (_helper as ModelViewHtmlHelper<IEnumerable<TModel>>).Link(command.Text, link).Render());
			}
			return result;
		}

		public override object GetData(TModel source) {
			var dataCommands = _commands == null ? null : _commands.Where(c => c.Position.HasFlag(GridCommandPosition.DataRow));
			if (dataCommands == null) {
				var newCommands = new GridCommandBuilder<TModel>(_helper, _keyExpression);
				newCommands.ForDataRowAsAction("View", "View");
				newCommands.ForDataRowAsAction("Edit", "Edit");
				newCommands.ForDataRowAsAction("Delete", "Delete");
				dataCommands = newCommands.Where(c => c.Position.HasFlag(GridCommandPosition.DataRow));
			}
			var result = string.Empty;
			foreach (IGridCommandBase<TModel> command in dataCommands.Where(c => c.Position.HasFlag(GridCommandPosition.DataRow))) {
				var link = string.Empty;
				if (command is GridCommand<TModel>)
					link = (command as GridCommand<TModel>).GetLink();
				else if (command is GridActionCommand<TModel>)
					link = (command as GridActionCommand<TModel>).RouteValues(new { key = _value(source) }).GetLink();
				else if (command is GridRouteCommand<TModel>)
					link = (command as GridRouteCommand<TModel>).RouteValues(new { key = _value(source) }).GetLink();
				else
					throw new Exception("Invalid command type");
				result += (result == string.Empty ? string.Empty : _commandsSeparator) + _helper is ModelViewAjaxHelper<IEnumerable<TModel>> ? (_helper as ModelViewAjaxHelper<IEnumerable<TModel>>).Link(command.Text, link).Render() : (_helper as ModelViewHtmlHelper<IEnumerable<TModel>>).Link(command.Text, link).Render();
			}
			return result;
		}
	}
}
